package com.wmz.config;

import com.auth0.jwt.JWT;
import com.wmz.config.filter.JwtFilter;
import com.wmz.config.handler.MyAuthenticationFailureHandler;
import com.wmz.config.handler.MyAuthenticationSuccessHandler;
import com.wmz.config.handler.MyLogoutSuccessHandler;
import com.wmz.constant.Constants;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

/**
 * @author wmz
 * @date 2024/2/16 0:04
 * @description SecurityConfig
 */
@Configuration //这是配置类，相当于原来spring的xml配置
public class SecurityConfig {
    @Resource
    private  MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
    @Resource
    private  MyAuthenticationFailureHandler myAuthenticationFailureHandler;
    @Resource
    private MyLogoutSuccessHandler myLogoutSuccessHandler;
    @Resource
    private JwtFilter jwtFilter;

    @Bean //创建加密器，解决There is no PasswordEncoder mapped for the id "null"错误
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    /**
     *配置spring security的行为
     * @param httpSecurity
     * @param configurationSource
     * @return
     * @throws Exception
     */
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity,CorsConfigurationSource configurationSource) throws Exception{
        // 禁用跨站请求伪造
        return httpSecurity
                .formLogin((formLogin) -> {
                    formLogin.loginProcessingUrl("/api/login")      //登录处理地址，不需要写Controller
                            .usernameParameter("loginAct")          //登录的用户名
                            .passwordParameter("loginPwd")          //登录的密码
                            .successHandler(myAuthenticationSuccessHandler)                       //登录成功的处理方式
                            .failureHandler(myAuthenticationFailureHandler);                      //登录失败的处理方式
                })
                .authorizeHttpRequests((authorize) -> {
                    authorize.requestMatchers(Constants.LOGIN_URI).permitAll()     //允许该请求通过
                            .anyRequest().authenticated();     //其他任何请求都需要登陆后才能访问
                })

                //方法引用，禁用跨站请求伪造，因为前后端分离的请求，没有传_csrf这个随机字符串
                .csrf(AbstractHttpConfigurer::disable)

                //解决spring security跨域问题
                .cors((cors) -> {
                    cors.configurationSource(configurationSource);
                })

                //禁用session
                .sessionManagement((session) -> {       //spring security默认使用session记住当前登录人的信息
                    //session创建策略
                    session.sessionCreationPolicy(SessionCreationPolicy.STATELESS); //无session状态，前后端分离，默认禁用session
                })

                //添加自定义的Filter
                .addFilterBefore(jwtFilter, LogoutFilter.class)

                //退出登录
                .logout((logout) -> {
                    logout.logoutUrl("/api/logout")     //退出登录的接口地址
                          .logoutSuccessHandler(myLogoutSuccessHandler);  //退出成功，就执行该handler，在handler中给前端返回json
                })
                .build();
    }

    @Bean
    public CorsConfigurationSource configurationSource(){
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));    //允许任何来源：http://localhost:8081
        configuration.setAllowedMethods(Arrays.asList("*"));    //允许任何请求方法：post,get,put,delete
        configuration.setAllowedHeaders(Arrays.asList("*"));    //允许任何请求头

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**",configuration);  //任何路径，都采用configuration这种策略
        return source;
    }
}
